<?php
class ViRegistration_Controller extends AdminController {

    public $PAYMENTS_VISIBLE_PROPERTY = 'admin/viRegistration/display/paymentsVisible';
    public $DISPLAY_PAYMENT_LIST_UUID = 'admin/viRegistration/display/personList';

    public function __construct() {
        parent::__construct('viRegistration');
        $this->setDefaultListOrder('begin_date');
        $this->viewData['renderedInAdminSpace'] = TRUE;
    }

    public function index() {
        return $this->all();
    }

    public function all() {
        $this->initPagination('vi_registration');

        $query = 'SELECT reg.*, sem.name, per.first_name, per.last_name, vat.name AS vi_accomodation_type_name ' .
                'FROM vi_registration reg ' .
                'LEFT OUTER JOIN vi_seminar sem ON sem.id = reg.vi_seminar_id ' .
                'LEFT OUTER JOIN person per ON per.id = reg.person_id ' .
                'LEFT OUTER JOIN vi_accomodation_type vat ON vat.code = reg.vi_accomodation_type_code ';
        $queryParams = array();

        // Search criteria
        $whereClause = '';
        $whereParams = array();
        $searchCriteria = $this->getSearchCriteria();
        foreach ($searchCriteria as $key => $value) {
            if ($value === NULL || trim($value) === '') {
                continue;
            }
            if ($key == 'person') {
                continue;
            }
            $whereClause .= 'reg.' . $key . ' = :' . $key . ' AND ';
            $queryParams[$key] = $value;
        }
        if ($whereClause) {
            $query .= 'WHERE ' . substr($whereClause, 0, -4);
        }

        $this->viewData['viRegistrationList'] = $this->dao->queryAll(
                $this->orderLimitAndOffset($query), $queryParams);

        // Quick search values
        $quickSearchValues = array();
        $quickSearchList = $this->dao->queryAll(
                'SELECT reg.id, sem.name, sem.begin_date, sem.end_date, per.first_name, per.last_name ' .
                'FROM vi_registration reg ' .
                'LEFT OUTER JOIN vi_seminar sem ON sem.id = reg.vi_seminar_id ' .
                'LEFT OUTER JOIN person per ON per.id = reg.person_id');
        foreach ($quickSearchList as $viRegistration) {
            $quickSearchValues[$viRegistration['id']] = $viRegistration['first_name'] . ' ' . $viRegistration['last_name'] . ' - ' . $viRegistration['name'] .
                    ' (' . format::date($viRegistration['begin_date']) . ' - ' . format::date($viRegistration['end_date']) . ')';
        }
        $this->viewData['viRegistrationOptions'] = $quickSearchValues;

        $this->renderMySubview('viRegistrationList');
    }

    public function display() {
        $id = $this->input->get('id');

        if (! valid::isId($id)) {
            $this->redirectToList('error.invalidId');
        }

        $viRegistration = $this->dao->getById('vi_registration', $id);
        if (! $viRegistration) {
            $this->redirectToList('error.recordNotFound');
        }

        $this->mergeViewData(registrationHelper::loadViDisplayData($viRegistration, $this->dao));

        // Load the payments
        $this->viewData['paymentList'] = $this->dao->queryAll(sql::orderBy($this->DISPLAY_PAYMENT_LIST_UUID,
                'SELECT pay.*, per.first_name, per.last_name ' .
                'FROM vi_registration_payment pay ' .
                'JOIN person per ON per.id = pay.created_by_id ' .
                'WHERE vi_registration_id = :vi_registration_id ', 'vi_registration_id'),
                array('vi_registration_id' => $id));

        $this->renderMySubview('viRegistrationDisplay');
    }

    public function edit() {
        $id = $this->input->get('id');
        $resume = $this->input->get('resume');

        if ($resume && $this->getSessionData()->viRegistration) {
            $id = $this->getSessionData()->viRegistration['vi_registration_id'];
        }
        else {
            $this->getSessionData()->viRegistration = NULL;
        }

        $viRegistration = $this->dao->getById('vi_registration', $id);
        if (! $viRegistration) {
            $this->redirectToList('error.recordNotFound');
        }
        if ($this->getSessionData()->viRegistration) {
            $viRegistration = array_merge($viRegistration, $this->getSessionData()->viRegistration);
        }
        $viSeminar = $this->dao->fetchViSeminarWithPrices($viRegistration['vi_seminar_id']);

        // We must calculate the prices after calling loadViDisplayData in order to have all required data.
        $viewData = registrationHelper::loadViDisplayData($viRegistration, $this->dao);
        $viewData['optionsForm'] = registrationHelper::calculateTotalPrice($viRegistration, 
                $viewData['optionsForm'], $viSeminar['prices-' . $viRegistration['currency_code']]);
        $this->mergeViewData($viewData);
        $this->viewData['optionsForm']['vi_registration_id'] = $id;

        $bankPaymentDiscount = $viewData['viSeminar']['prices-' . ViregWizardData::$CURRENCY_CODE]['bank_payment_discount'];
        $this->viewData['paymentTypeOptions'] = registrationHelper::getPaymentOptions(
        		$viSeminar,
                $viRegistration['is_instructor'], $bankPaymentDiscount, ViregWizardData::$CURRENCY_CODE);

        $this->renderMySubview('viRegistrationEdit');
    }

    protected function loadFormData() {
    }

    public function save() {
        $optionsForm = $this->postToDbValues();
        $this->getSessionData()->viRegistration = $optionsForm;
        $id = $optionsForm['vi_registration_id'];

        if (! valid::isId($id)) {
            $this->redirectToList('error.invalidId');
        }

        // Basic validation
        $ev = new EntityValidator($optionsForm, 'viRegistration', $this->msg);
        $ev->decimal('course_fee');
        $ev->required('vi_accomodation_type_code');
        $ev->required('payment_type');
        if ($this->msg->hasErrors()) {
            $this->redirect('/admin/viRegistration/edit?resume=1');
        }

        $viRegistration = $this->dao->getById('vi_registration', $id);
        if (! $viRegistration) {
            $this->redirectToList('error.recordNotFound');
        }
        
        $viSeminar = $this->dao->fetchViSeminarWithPrices($viRegistration['vi_seminar_id']);
        
        $origianalTotalPrice = $viRegistration['total_price'];

        // If the payment type has changed adjust tha bank_payment_discount.
        if ($viRegistration['payment_type'] != 'bank') {
        	if ($optionsForm['payment_type'] == 'bank') {
        		$bankPaymentDiscount = $viSeminar['prices-' . ViregWizardData::$CURRENCY_CODE]['bank_payment_discount'];
        		$viRegistration['bank_payment_discount'] = $bankPaymentDiscount;
        		$this->msg->info('viRegistration-bankPaymentDiscountSet', format::price($viRegistration['bank_payment_discount'], $viRegistration['currency_code']));
        	}
        }
        else {
        	if ($optionsForm['payment_type'] != 'bank') {
        		if ($viRegistration['bank_payment_discount']) {
        			$viRegistration['bank_payment_discount'] = 0;
        			$this->msg->warning('viRegistration-bankPaymentDiscountCleared-warning');
        		}
        	}
        }
        
        // Calculate prices of the registration
        $optionsForm['viAccomodationType'] = $this->dao->fetchViAccomodationTypeForSeminar(
                $viSeminar['id'], $optionsForm['vi_accomodation_type_code']);
        $optionsForm = registrationHelper::calculateTotalPrice($viRegistration, $optionsForm, $viSeminar['prices-' . $viRegistration['currency_code']]);

        // Copy the fields that could be modified to the registration object
        $propertiesToCopy = array(
            'course_fee', 'vi_accomodation_type_code', 'last_meal_in_package',
            'payment_type', 'notes', 'meals_price', 'total_price',
            'accomodation_price', 'social_discount_applied', 'is_present', 'extra_discount');
        foreach ($propertiesToCopy as $property) {
            $viRegistration[$property] = $optionsForm[$property];
        }
        
        if ($origianalTotalPrice != $viRegistration['total_price']) {
        	$this->msg->info('viRegistration-totalPriceChanged',
        			format::price($origianalTotalPrice, $viRegistration['currency_code']),
        			format::price($viRegistration['total_price'], $viRegistration['currency_code']));
        }

        // Save the registration and its meal selection
        $this->dao->getDb()->beginTransaction();
        try {
            $this->dao->update('vi_registration', $viRegistration);
            if (is_array($optionsForm['mealSelection'])) {
                $this->dao->saveMealSelection($optionsForm['mealSelection'], $id);
            }
            $this->dao->getDb()->commit();
            $this->msg->info('viRegistration.editSuccess', $id);
        }
        catch (Exception $e) {
            $this->dao->getDb()->rollBack();
            $this->msg->error('error.dbException', $e->getCode());
            Kohana::log('error', $e);
        }
        
        $this->redirect('/admin/viRegistration/display?id=' . $id);
    }

    public function saveForm() {
        $optionsForm = $this->postToDbValues();
        $viSeminar = $this->dao->getViSeminarByRegistrationId($optionsForm['vi_registration_id']);
        $viSeminar = $this->dao->fetchViSeminarWithPrices($viSeminar['id']);
        $this->getSessionData()->viRegistration = registrationHelper::processSavedForm(
                $optionsForm, $this->getSessionData()->viRegistration, $viSeminar);
        $this->redirect('/admin/viRegistration/edit?resume=1');
    }

    public function delete() {
        // TODO
    }

    /*
    public function changeCourseFee() {
        $formData = $this->postToDbValues();
        $id = $formData['vi_registration_id'];
        $courseFee = $formData['course_fee'];

        $viRegistration = $this->dao->getById('vi_registration', $id);
        if (! $viRegistration) {
            $this->redirectToList('error.recordNotFound');
        }
        if (! valid::isPositiveDecimalOrZero($courseFee)) {
            $this->msg->error('error.notPositiveDecimalOrZero', 'viRegistration.newCourseFee');
            $this->redirect('/admin/viRegistration/display?id=' . $id);
        }

        $viRegistration['course_fee'] = $courseFee;
        $viRegistration['total_price'] = $this->calculateRegistrationTotalPrice($viRegistration);

        $this->dao->update('vi_registration', $viRegistration);

        $this->msg->info('viRegistration.courseFeeWasChanged', $courseFee,
                text::get('currency.mark-' . $viRegistration['currency_code']));
        $this->redirect('/admin/viRegistration/display?id=' . $id);
    }

    public function changeNightCount() {
        $formData = $this->postToDbValues();
        $id = $formData['vi_registration_id'];
        $nightCount = $formData['night_count'];

        $viRegistration = $this->dao->getById('vi_registration', $id);
        if (! $viRegistration) {
            $this->redirectToList('error.recordNotFound');
        }
        if (! valid::isPositiveIntegerOrZero($nightCount)) {
            $this->msg->error('error.notPositiveIntegerOrZero', 'viRegistration.newNightCount');
            $this->redirect('/admin/viRegistration/display?id=' . $id);
        }

        // Calculate the new price of accomodation
        $viAccomodationTypePriceList = $this->dao->getByFieldsOfEntity(
                'vi_seminar_accomodation_type_price', $viRegistration,
                array('vi_accomodation_type_code', 'vi_seminar_id', 'currency_code'));
        // TODO: check there is exactly one record returned
        $oneNightPrice = $viAccomodationTypePriceList[0]['price'];
        $accomodationPrice = bcmul($nightCount, $oneNightPrice, sql::$DECIMAL_PRECISION);

        $viRegistration['night_count'] = $nightCount;
        $viRegistration['accomodation_price'] = $accomodationPrice;
        $viRegistration['total_price'] = $this->calculateRegistrationTotalPrice($viRegistration);

        $this->dao->update('vi_registration', $viRegistration);

        $this->msg->info('viRegistration.nightCountWasChanged', $nightCount);
        $this->redirect('/admin/viRegistration/display?id=' . $id);
    }
    */

    public function togglePresence() {
        $id = $this->input->post('id');

        if (! valid::isId($id)) {
            $this->redirectToList('error.invalidId');
        }

        $viRegistration = $this->dao->getById('vi_registration', $id);
        if (! $viRegistration) {
            $this->redirectToList('error.recordNotFound');
        }

        $viRegistration['is_present'] = ! $viRegistration['is_present'];
        $this->dao->update('vi_registration', $viRegistration);

        if (request::is_ajax()) {
            AjaxXmlResponseBuilder::sendUpdate('presence_' . $id, format::twoValueBoolean($viRegistration['is_present']));
        }
        else {
            $participant = $this->dao->getById('person', $viRegistration['person_id']);
            if ($viRegistration['is_present']) {
                $this->msg->info('viRegistration.participantSetPresent', $participant['first_name'] . ' ' . $participant['last_name']);
            }
            else {
                $this->msg->info('viRegistration.participantSetNotPresent', $participant['first_name'] . ' ' . $participant['last_name']);
            }
            $this->redirectBack();
        }
    }

    /** Calculates the total price as a sum of accomodation, meals and course fee. */
    /*
    private function calculateRegistrationTotalPrice($viRegistration) {
    	$total = $viRegistration['accomodation_price'];
    	$total = bcadd($total, $viRegistration['meals_price'], sql::$DECIMAL_PRECISION);
    	$total = bcadd($total, $viRegistration['course_fee'], sql::$DECIMAL_PRECISION);
    	$total = bcsub($total, $viRegistration['bank_payment_discount'], sql::$DECIMAL_PRECISION);
        return $total;
    }
    */

    public function exportToExcel() {

        $viRegistrationList = $this->dao->queryAll(
                'SELECT reg.*, sem.name, per.first_name, per.last_name, vat.name AS vi_accomodation_type_name ' .
                'FROM vi_registration reg ' .
                'LEFT OUTER JOIN vi_seminar sem ON sem.id = reg.vi_seminar_id ' .
                'LEFT OUTER JOIN person per ON per.id = reg.person_id ' .
                'LEFT OUTER JOIN vi_accomodation_type vat ON vat.code = reg.vi_accomodation_type_code');

        excel::loadClasses();

        // require Kohana::find_file('vendor', 'PHPExcel/Classes/Writer/Excel2007.php');

        $objPHPExcel = new PHPExcel();

        // Metadata
        excel::setMetadata($objPHPExcel);
        $objPHPExcel->setActiveSheetIndex(0);
        $sheet = $objPHPExcel->getActiveSheet();
        
        // Headers
        $sheet->setCellValue('A1', text::get('viRegistration.id'));
        $sheet->setCellValue('B1', text::get('viSeminar.name'));
        $sheet->setCellValue('C1', text::get('viRegistration.person_id'));
        $sheet->setCellValue('D1', text::get('viRegistration.vi_accomodation_type_code'));
        $sheet->setCellValue('E1', text::get('viRegistration.created_at'));
        $sheet->setCellValue('F1', text::get('viRegistration.create_time'));
        $sheet->setCellValue('G1', text::get('viRegistration.total_price'));
        $sheet->setCellValue('H1', text::get('viRegistration.currency_code'));
        $sheet->setCellValue('I1', text::get('viRegistration.social_discount'));
        $sheet->setCellValue('J1', text::get('viRegistration.payment_type'));


        // Values
        $rowNumber = 2;
        foreach ($viRegistrationList as $viRegistration) {
            $sheet->setCellValue('A' . $rowNumber, $viRegistration['id']);
            $sheet->setCellValue('B' . $rowNumber, $viRegistration['name']);
            $sheet->setCellValue('C' . $rowNumber, $viRegistration['first_name'] . ' ' . $viRegistration['last_name']);
            $sheet->setCellValue('D' . $rowNumber, $viRegistration['vi_accomodation_type_name']);
            $sheet->setCellValue('E' . $rowNumber, format::date($viRegistration['created_at']));
            // $sheet->getStyle('E' . $rowNumber)->getNumberFormat()->setFormatCode(PHPExcel_Style_NumberFormat::FORMAT_DATE_XLSX15);
            $sheet->setCellValue('F' . $rowNumber, $viRegistration['create_time']);
            $sheet->setCellValue('G' . $rowNumber, $viRegistration['total_price']);
            $sheet->setCellValue('H' . $rowNumber, text::get('currency.mark-' . $viRegistration['currency_code']));
            $sheet->setCellValue('I' . $rowNumber, format::boolean($viRegistration['social_discount']));
            $sheet->setCellValue('J' . $rowNumber, text::get('viregWizard.paymentType-' . $viRegistration['payment_type']));
            $rowNumber ++;
        }

        // Fonts
        /*
        $objPHPExcel->getActiveSheet()->getStyle('B1')->getFont()->setName('Candara');
        $objPHPExcel->getActiveSheet()->getStyle('B1')->getFont()->setSize(20);
        $objPHPExcel->getActiveSheet()->getStyle('B1')->getFont()->setBold(true);
        $objPHPExcel->getActiveSheet()->getStyle('B1')->getFont()->getColor()->setARGB(PHPExcel_Style_Color::COLOR_WHITE);
        $objPHPExcel->getActiveSheet()->getStyle('B1')->getFont()->setName('Candara');
        $objPHPExcel->getActiveSheet()->getStyle('B1')->getFont()->setSize(20);
        $objPHPExcel->getActiveSheet()->getStyle('B1')->getFont()->setBold(true);
        $objPHPExcel->getActiveSheet()->getStyle('B1')->getFont()->getColor()->setARGB(PHPExcel_Style_Color::COLOR_WHITE);
        */

        // Borders
        // $objPHPExcel->getActiveSheet()->getStyle('A3')->getBorders()->getTop()->setBorderStyle(PHPExcel_Style_Border::BORDER_THIN);

        // Save the file
        $fileName = tempNam(Kohana::config('yosemin.temp_dir'), 'yoseminXlsx');
        $objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel2007');
        $objWriter->save($fileName);

        download::force($fileName, NULL, 'export.xlsx');
    }

    /*
    function downloadFile($path, $downloadName=NULL) {
        if (! $downloadName) {
            $downloadName = basename($path);
        }

        // addition by Jorg Weske
        $fileExtension = strtolower(substr(strrchr($path, "."), 1));

        if($path == "") {
            echo 'No File name.';
            exit;
        }
        else if (! file_exists($path)) {
            echo 'File does not exist.';
            exit;
        }
        
        switch($fileExtension) {
            case 'pdf' : $contentType = 'application/pdf'; break;
            case 'exe' : $contentType = 'application/octet-stream'; break;
            case 'zip' : $contentType = 'application/zip'; break;
            case 'doc' : $contentType = 'application/msword'; break;
            case 'xls' : $contentType = 'application/vnd.ms-excel'; break;
            case 'ppt' : $contentType = 'application/vnd.ms-powerpoint'; break;
            case 'gif' : $contentType = 'image/gif'; break;
            case 'png' : $contentType = 'image/png'; break;
            case 'jpeg':
            case 'jpg' : $contentType = 'image/jpg'; break;
            default: $contentType = 'application/octet-stream';
        }

        header('Pragma: public'); // required
        header('Expires: 0');
        header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
        header('Cache-Control: private', false); // required for certain browsers
        header('Content-Type: ' . $contentType);
        // change, added quotes to allow spaces in filenames, by Rajkumar Singh
        header('Content-Disposition: attachment; filename="' . $downloadName . '";');
        header('Content-Transfer-Encoding: binary');
        header('Content-Length: ' . filesize($path));
        readfile($path);
        exit();
    }
     */

    public function paymentList() {
        
    }

    public function paymentDisplay() {
        $id = $this->input->get('id');

        if (! valid::isId($id)) {
            $this->redirectToList('error.invalidId');
        }

        $payment = $this->dao->getById('vi_registration_payment', $id);
        if (! $payment) {
            $this->redirectToList('error.recordNotFound');
        }
        $this->viewData['payment'] = $payment;

        $this->viewData['viRegistration'] = $this->dao->getById('vi_registration', $payment['vi_registration_id']);

        $this->renderMySubview('viRegistrationPaymentDisplay');
    }

    public function paymentCreate() {
        $viRegistrationId = $this->input->get('viRegistrationId');

        if (! valid::isId($viRegistrationId)) {
            $this->redirectToList('error.invalidId');
        }

        $viRegistration = $this->dao->getById('vi_registration', $viRegistrationId);
        if (! $viRegistration) {
            $this->redirectToList('error.recordNotFound');
        }
        $this->viewData['viRegistration'] = $viRegistration;

        $payment = array('vi_registration_id' => $viRegistrationId);
        if (! $payment['payment_date']) {
            $payment['payment_date'] = date::today();
        }
        if (! $payment['payment_time']) {
            $payment['payment_time'] = date('G:i');
        }
        $this->viewData['payment'] = $payment;
        
        $this->renderMySubview('viRegistrationPaymentEdit');
    }

    public function paymentEdit() {
        $paymentId = $this->input->get('paymentId');

        if (! valid::isId($paymentId)) {
            $this->redirectToList('error.invalidId');
        }

        $payment = $this->dao->getById('vi_registration_payment', $paymentId);
        if (! $payment) {
            $this->redirectToList('error.recordNotFound');
        }

        $viRegistration = $this->dao->getById('vi_registration', $payment['vi_registration_id']);
        $this->viewData['viRegistration'] = $viRegistration;

        $this->viewData['payment'] = $payment;

        $this->renderMySubview('viRegistrationPaymentEdit');
    }

    public function paymentSave() {
        $formData = $this->postToDbValues();
        $this->viewData['payment'] = $formData;
        $viRegistrationId = $formData['vi_registration_id'];

        if (! valid::isId($viRegistrationId)) {
            $this->redirectToList('error.invalidId');
        }

        $viRegistration = $this->dao->getById('vi_registration', $viRegistrationId);
        if (! $viRegistration) {
            $this->redirectToList('error.recordNotFound');
        }
        $this->viewData['viRegistration'] = $viRegistration;

        $viSeminar = $this->dao->getById('vi_seminar', $viRegistration['vi_seminar_id']);

        $person = $this->dao->getById('person', $viRegistration['person_id']);

        $ev = new EntityValidator($formData, 'viRegistration', $this->msg);
        // $ev->required('record_number');
        $ev->decimal('paid_amount');
        $ev->date('payment_date');
        $ev->timeOrNull('payment_time');
        if ($this->msg->hasErrors()) {
            $this->publishErrors('admin/viRegistration/viRegistrationPaymentEdit');
            return;
        }

        if ($formData['record_number']) {
            if ($this->dao->alreadyExists('vi_registration_payment', 'record_number', $formData)) {
                $this->msg->error('viRegistration.paymentAlreadyExists-recordNumber', $formData['record_number']);
                $this->publishErrors('admin/viRegistration/viRegistrationPaymentEdit');
            }
        }

        $paymentName = '"' . $formData['record_number'] . '"';
        if (! $paymentName) {
            $paymentName = format::decimal($formData['paid_amount']) . ' ' . text::get('currency.mark-' . $viRegistration['currency_code']);
        }

        if (sql::isPersistent($formData)) {
            $this->dao->update('vi_registration_payment', $formData);
            $this->msg->info('viRegistration.paymantEditSuccess', $paymentName, $viRegistrationId);
        }
        else {
            $this->dao->insert('vi_registration_payment', $formData);
            $this->msg->info('viRegistration.paymantCreateSuccess', $paymentName, $viRegistrationId);
        }

        /*
        if (! $viRegistration['is_present'] && $formData['is_present']) {
            $viRegistration['is_present'] = $formData['is_present'];
            $this->dao->update('vi_registration', $viRegistration);
            $participant = $this->dao->getById('person', $viRegistration['person_id']);
            $this->msg->info('viRegistration.participantSetPresent', $participant['first_name'] . ' ' . $participant['last_name']);
        }
        */

        if (registrationHelper::isBankPayment($formData['record_number'])) {
            // Send an email to the user about getting the payment.
            $emailBody = text::getInLang($person['preferred_language'], 'viRegistration.paymentReceivedEmail-body',
					array(
							$viSeminar['name'],
							$formData['paid_amount'] . ' ' . text::getInLang($person['preferred_language'], 'currency.mark-' . $viRegistration['currency_code'])
					));
            $mailResult = email::sendInUtf8(
                    $person['first_name'] . ' ' . $person['last_name'],
                    $person['email'],
                    text::getInLang($person['preferred_language'], 'viRegistration.paymentReceivedEmail-title'),
                    email::addHeadingAndClosing($emailBody, $person));
            if (! $mailResult) {
                $this->msg->warning('viregWizard.mailFailedRegistrationValid');
            }
        }

        // Do not display the messages if this is an AJAX call. The page will be reloaded
        // after a successful request and then the messages will be displayed on the
        // main page (not in the form popup).
        $this->ajaxSuccessOrRedirect('/admin/viRegistration/display?id=' . $viRegistrationId, $paymentRecord, FALSE);
    }

    public function paymentDelete() {
        $id = $this->input->get('id');

        if (! valid::isId($id)) {
            $this->redirectToList('error.invalidId');
        }

        $payment = $this->dao->getById('vi_registration_payment', $id);
        if (! $payment) {
            $this->msg->error('error.recordNotFound');
            $this->redirectBack();
        }

        $viRegistration = $this->dao->getById('vi_registration', $payment['vi_registration_id']);

        $this->dao->delete('vi_registration_payment', $id);

        $paymentName = '"' . $formData['record_number'] . '"';
        if (! $paymentName) {
            $paymentName = format::decimal($payment['paid_amount']) . ' ' . text::get('currency.mark-' . $viRegistration['currency_code']);
        }

        $this->msg->info('viRegistration.paymentDeleteSuccess', $paymentName, $viRegistration['id']);
        $this->redirectBack();
    }

    public function cancel() {
        $viRegistrationId = $this->input->post('id');

        if (! valid::isId($viRegistrationId)) {
            $this->redirect('/user/viRegistration/all');
        }

        $viRegistration = $this->dao->getById('vi_registration', $viRegistrationId);
        if (! $viRegistration) {
            $this->redirectToList('error.recordNotFound');
        }

        $person = $this->dao->getById('person', $viRegistration['person_id']);
        $viSeminar = $this->dao->getById('vi_seminar', $viRegistration['vi_seminar_id']);
        if (! registrationUtils::canBeCancelled($viRegistration, $viSeminar)) {
            $this->redirectToList('viRegistration.cannotBeCancelled');
        }
        $viRegistration['cancelled_at'] = time();

        // TODO cancel fee or someting
        $this->dao->update('vi_registration', $viRegistration);
        $this->msg->info('myRegistration.cancellationSuccess', $viSeminar['name']);

        // Send a confirmation email to the user.
        $mailResult = email::sendInUtf8(
                $person['first_name'] . ' ' . $person['last_name'],
                $person['email'],
                text::getInLang($person['preferred_language'], 'myRegistration-cancellationEmail-subject'),
                text::getInLang($person['preferred_language'], 'myRegistration-cancellationEmail-body', $viSeminar['name']));
        if (! $mailResult) {
            $this->msg->warning('viregWizard.mailFailedRegistrationValid');
        }

        $this->redirectBack();
    }

    public function keyDepositForm() {
        $viRegistrationId = $this->input->get('id');

        if (! valid::isId($viRegistrationId)) {
            $this->redirectToList('error.invalidId');
        }

        $viRegistration = $this->dao->getById('vi_registration', $viRegistrationId);
        if (! $viRegistration) {
            $this->redirectToList('error.recordNotFound');
        }

        $formData = array();
        $formData['vi_registration_id'] = $viRegistration['id'];
        $formData['key_deposit'] = $viRegistration['key_deposit'];
        $formData['is_key_returned'] = $viRegistration['is_key_returned'] ? sql::$TRUE : sql::$FALSE;
        $this->viewData['viRegistration'] = $viRegistration;
        $this->viewData['formData'] = $formData;

        $this->renderMySubview('viRegistrationKeyDeposit');
    }

    public function keyDepositSave() {
        $formData = $this->postToDbValues();
        $this->viewData['formData'] = $formData;
        $viRegistrationId = $formData['vi_registration_id'];

        if (! valid::isId($viRegistrationId)) {
            $this->redirectToList('error.invalidId');
        }

        $viRegistration = $this->dao->getById('vi_registration', $viRegistrationId);
        if (! $viRegistration) {
            $this->redirectToList('error.recordNotFound');
        }

        $ev = new EntityValidator($formData, 'viRegistration', $this->msg);
        if ($formData['key_deposit']) {
            $ev->positiveDecimalOrZero('key_deposit');
        }
        if ($this->msg->hasErrors()) {
            $this->publishErrors('admin/viRegistration/viRegistrationKeyDeposit');
            return;
        }

        if ($viRegistration['key_deposit']) {
            $viRegistration['is_key_returned'] = $formData['is_key_returned'];
        }
        $viRegistration['key_deposit'] = $formData['key_deposit'];
        $this->dao->update('vi_registration', $viRegistration);

        $this->redirectBack();
    }

    protected function searchData() {
        // Weekend seinar list
        $viSeminarList = $this->dao->queryAll(
                'SELECT id, name, begin_date, end_date FROM vi_seminar ORDER BY begin_date DESC');
        $this->viewData['viSeminarOptions'] = array();
        foreach ($viSeminarList as $viSeminar) {
            $this->viewData['viSeminarOptions'][$viSeminar['id']] = $viSeminar['name'] .
                    ' (' . format::date($viSeminar['begin_date']) . ' - ' . format::date($viSeminar['end_date']) . ')';
        }

        // Person list
        $personList = $this->dao->queryAll(
                'SELECT id, first_name, last_name, birth_date FROM person ' .
                'ORDER BY last_name ASC, first_name ASC');
        $this->viewData['personOptions'] = array();
        foreach ($personList as $person) {
            $this->viewData['personOptions'][$person['id']] = $person['first_name'] . ' ' .
                    $person['last_name'] . ' (' . format::date($person['birth_date']) . ')';
        }

        // Payment types
        $this->viewData['paymentTypeOptions'] = array(
            'bank' => text::get('viregWizard.paymentType-bank'),
            'cash' => text::get('viregWizard.paymentType-cash'),
            'honorarium' => text::get('viregWizard.paymentType-honorarium')
        );

        // Accomodation types
        $this->viewData['viAccomodationTypeOptions'] = $this->dao->queryOptions(
                'SELECT code, name FROM vi_accomodation_type ' .
                'WHERE code IN (SELECT DISTINCT vi_accomodation_type_code FROM vi_registration) ' .
                'ORDER BY name');
    }
}
